static void m0_configure_ddr(struct pll_div pll_div, uint32_t ddr_index)
{
- /* set PARAM to M0_FUNC_DRAM */
- mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_DRAM);
-
mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(pll_div.fbdiv));
mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON1,
POSTDIV2(pll_div.postdiv2) | POSTDIV1(pll_div.postdiv1) |
mmio_write_32(M0_PARAM_ADDR + PARAM_FREQ_SELECT, ddr_index << 4);
dmbst();
+ m0_configure_execute_addr(M0_BINCODE_BASE);
}
static uint32_t prepare_ddr_timing(uint32_t mhz)
# Build platform
PLAT_M0 ?= rk3399m0
+PLAT_M0_PMU ?= rk3399m0pmu
ifeq (${V},0)
Q=@
-I../../include/shared/
# NOTE: Add C source files here
-C_SOURCES := src/startup.c \
- src/main.c \
- src/suspend.c \
- src/dram.c \
+C_SOURCES_COMMON := src/startup.c
+C_SOURCES := src/dram.c \
src/stopwatch.c
+C_SOURCES_PMU := src/suspend.c
# Flags definition
COMMON_FLAGS := -g -mcpu=$(ARCH) -mthumb -Wall -O3 -nostdlib -mfloat-abi=soft
$(notdir $(patsubst %.S,%.o,$(filter %.S,$(1))))
endef
+SOURCES_COMMON := $(C_SOURCES_COMMON)
SOURCES := $(C_SOURCES)
+SOURCES_PMU := $(C_SOURCES_PMU)
+OBJS_COMMON := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_COMMON)))
OBJS := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES)))
+OBJS_PMU := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_PMU)))
LINKERFILE := $(BUILD)/$(PLAT_M0).ld
MAPFILE := $(BUILD)/$(PLAT_M0).map
+MAPFILE_PMU := $(BUILD)/$(PLAT_M0_PMU).map
ELF := $(BUILD)/$(PLAT_M0).elf
+ELF_PMU := $(BUILD)/$(PLAT_M0_PMU).elf
BIN := $(BUILD)/$(PLAT_M0).bin
+BIN_PMU := $(BUILD)/$(PLAT_M0_PMU).bin
LINKERFILE_SRC := src/$(PLAT_M0).ld.S
# Function definition related compilation
$(and $(REMAIN),$(error Unexpected source files present: $(REMAIN)))
endef
-.DEFAULT_GOAL := $(BIN)
+.PHONY: all
+all: $(BIN) $(BIN_PMU)
+
+.DEFAULT_GOAL := all
$(LINKERFILE): $(LINKERFILE_SRC)
$(CC) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF
[email protected] -MT $@ -o $@ $<
-include $(LINKERFILE).d
-$(ELF) : $(OBJS) $(LINKERFILE)
+$(ELF) : $(OBJS) $(OBJS_COMMON) $(LINKERFILE)
@echo " LD $@"
- $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS)
+ $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON)
-$(BIN) : $(ELF)
+%.bin : %.elf
@echo " BIN $@"
$(Q)$(OC) -O binary $< $@
+$(ELF_PMU) : $(OBJS_COMMON) $(OBJS_PMU) $(LINKERFILE)
+ @echo " LD $@"
+ $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON)
+
+$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_COMMON),$(1)))
$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES),$(1)))
+$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_PMU),$(1)))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
-void handle_suspend(void);
-void handle_dram(void);
void stopwatch_init_usecs_expire(unsigned int usecs);
int stopwatch_expired(void);
void stopwatch_reset(void);
mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_NORMAL_MODE));
}
-void handle_dram(void)
+__attribute__((noreturn)) void main(void)
{
mmio_setbits_32(PHY_REG(0, 927), (1 << 22));
mmio_setbits_32(PHY_REG(1, 927), (1 << 22));
deidle_port();
mmio_clrbits_32(PHY_REG(0, 927), (1 << 22));
mmio_clrbits_32(PHY_REG(1, 927), (1 << 22));
+
+ mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG);
+
+ for (;;)
+ __asm__ volatile ("wfi");
}
+++ /dev/null
-/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <m0_param.h>
-#include "rk3399_mcu.h"
-
-__attribute__((noreturn)) void main(void)
-{
- switch (mmio_read_32(PARAM_ADDR + PARAM_M0_FUNC)) {
- case M0_FUNC_SUSPEND:
- handle_suspend();
- break;
- case M0_FUNC_DRAM:
- handle_dram();
- break;
- default:
- break;
- }
-
- mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG);
-
- for (;;)
- __asm__ volatile ("wfi");
-}
#include "rk3399_mcu.h"
/* Stack configuration */
-#define STACK_SIZE 0x00000100
+#define STACK_SIZE 0x00000040
__attribute__ ((section(".co_stack")))
unsigned long pstack[STACK_SIZE];
#define SCR_SLEEPDEEP_SHIFT (1 << 2)
-void handle_suspend(void)
+__attribute__((noreturn)) void main(void)
{
unsigned int status_value;
+ /*
+ * PMU sometimes doesn't clear power mode bit as it's supposed to due
+ * to a hardware bug. Make the M0 clear it manually to be sure,
+ * otherwise interrupts some cases with concurrent wake interrupts
+ * we stay asleep forever.
+ */
while (1) {
status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
if (status_value) {
mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01);
- return;
+ break;
}
}
- /* m0 enter deep sleep mode */
- mmio_setbits_32(M0_SCR, SCR_SLEEPDEEP_SHIFT);
+ /*
+ * FSM power secquence is .. -> ST_INPUT_CLAMP(step.17) -> .. ->
+ * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP ->
+ * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> ..,
+ * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by
+ * power or other single glitch, but WAKEUP_RESET need work with 24MHz,
+ * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance
+ * that glitch will affect SOC, and mess up SOC status, so we
+ * addressmap_shared software clamp between ST_INPUT_CLAMP and
+ * ST_WAKEUP_RESET_CLR to avoid this happen.
+ */
+ while (1) {
+ status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
+ if (status_value >= 17) {
+ mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
+ break;
+ }
+
+ }
+
+ while (1) {
+ status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
+ if (status_value >= 26) {
+ mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
+ break;
+ }
+ }
+
+ for (;;)
+ __asm__ volatile ("wfi");
}
mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7));
mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), WMSK_BIT(12));
- /* set the execute address for M0 */
- mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3),
- BITS_WITH_WMASK((M0_BINCODE_BASE >> 12) & 0xffff,
- 0xffff, 0));
- mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7),
- BITS_WITH_WMASK((M0_BINCODE_BASE >> 28) & 0xf,
- 0xf, 0));
-
/* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */
mmio_setbits_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, 0x02);
mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, WMSK_BIT(5));
}
+void m0_configure_execute_addr(uintptr_t addr)
+{
+ /* set the execute address for M0 */
+ mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3),
+ BITS_WITH_WMASK((addr >> 12) & 0xffff,
+ 0xffff, 0));
+ mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7),
+ BITS_WITH_WMASK((addr >> 28) & 0xf,
+ 0xf, 0));
+}
+
void m0_start(void)
{
/* enable clocks for M0 */
#define M0_BINCODE_BASE ((uintptr_t)rk3399m0_bin)
#define M0_PARAM_ADDR (M0_BINCODE_BASE + PARAM_ADDR)
+#define M0PMU_BINCODE_BASE ((uintptr_t)rk3399m0pmu_bin)
/* pmu_fw.c */
extern char rk3399m0_bin[];
extern char rk3399m0_bin_end[];
+extern char rk3399m0pmu_bin[];
+extern char rk3399m0pmu_bin_end[];
+
extern void m0_init(void);
extern void m0_start(void);
extern void m0_stop(void);
extern void m0_wait_done(void);
+extern void m0_configure_execute_addr(uintptr_t addr);
#endif /* __M0_CTL_H__ */
}
}
-static void m0_configure_suspend(void)
-{
- /* set PARAM to M0_FUNC_SUSPEND */
- mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_SUSPEND);
-}
-
void sram_save(void)
{
size_t text_size = (char *)&__bl31_sram_text_real_end -
set_pmu_rsthold();
sys_slp_config();
- m0_configure_suspend();
+ m0_configure_execute_addr(M0PMU_BINCODE_BASE);
m0_start();
pmu_sgrf_rst_hld();
*/
/* convoluted way to make sure that the define is pasted just the right way */
-#define _INCBIN(file, sym) \
+#define _INCBIN(file, sym, sec) \
__asm__( \
- ".section .sram.incbin\n" \
+ ".section " #sec "\n" \
".global " #sym "\n" \
".type " #sym ", %object\n" \
".align 4\n" \
#sym "_end:\n" \
)
-#define INCBIN(file, sym) _INCBIN(file, sym)
+#define INCBIN(file, sym, sec) _INCBIN(file, sym, sec)
-INCBIN(RK3399M0FW, rk3399m0_bin);
+INCBIN(RK3399M0FW, rk3399m0_bin, ".sram.incbin");
+INCBIN(RK3399M0PMUFW, rk3399m0pmu_bin, ".pmusram.incbin");
ASSERT(. == ALIGN(64 * 1024),
".pmusram.entry request 64K aligned.");
*(.pmusram.entry)
+
__bl31_pmusram_text_start = .;
*(.pmusram.text)
*(.pmusram.rodata)
__bl31_pmusram_text_end = .;
+
+ /* M0 start address request 4K align */
+ . = ALIGN(4096);
+ __pmusram_incbin_start = .;
+ *(.pmusram.incbin)
+ __pmusram_incbin_end = .;
+
__bl31_pmusram_data_start = .;
*(.pmusram.data)
__bl31_pmusram_data_end = .;
-
} >PMUSRAM
}
#ifndef __M0_PARAM_H__
#define __M0_PARAM_H__
-#ifndef __LINKER__
-enum {
- M0_FUNC_SUSPEND = 0,
- M0_FUNC_DRAM = 1,
-};
-#endif /* __LINKER__ */
-
#define PARAM_ADDR 0xc0
#define PARAM_M0_FUNC 0x00
RK3399M0FW=${BUILD_M0}/${PLAT_M0}.bin
$(eval $(call add_define,RK3399M0FW))
+RK3399M0PMUFW=${BUILD_M0}/${PLAT_M0}pmu.bin
+$(eval $(call add_define,RK3399M0PMUFW))
+
HDCPFW=${RK_PLAT_SOC}/drivers/dp/hdcp.bin
$(eval $(call add_define,HDCPFW))
# CCACHE_EXTRAFILES is needed because ccache doesn't handle .incbin
export CCACHE_EXTRAFILES
-${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW)
+${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW):$(RK3399M0PMUFW)
${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c: $(RK3399M0FW)
${BUILD_PLAT}/bl31/cdn_dp.o: CCACHE_EXTRAFILES=$(HDCPFW)